#include "utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <QString>
#include <sys/types.h>
#include <QRegExp>
#include <QStringList>
#include <math.h>
#include <QMap>
#include <QVector>
#include "typedef.h"


bool isZero(float value){

    return fabs(value) <= FLOAT_EPS ;
}



uint16_t be_to_le(const uint16_t data)
{
    uint8_t tmpdata[2];
    tmpdata[0]=data>>8; //大端的高8位
    tmpdata[1]=data&0xff; //大端的低8位
    return (tmpdata[1]<<8)+tmpdata[0];
}

uint16_t le_to_be(const uint16_t data)
{
    uint8_t tmpdata[2];
    tmpdata[1]=data>>8;   //小端的高8位
    tmpdata[0]=data&0xff; //小端的低8位
    return (tmpdata[0]<<8)+tmpdata[1];
}

uint16_t be_ctos(const uint8_t *buf)
{
    return (buf[0] << 8) | buf[1];
}

int uint16Toint(uint16_t value){
    uint16_t iValue=~value+1;
    return 0-(int)iValue;
}

uint16_t le_ctos(const uint8_t *buf)
{
    return (buf[1] << 8) + buf[0];
}
uint8_t  hex2decimal(uint8_t value){

    return value/16*10+value%16;
}

uint8_t  decimal2hex(uint8_t value){
    return value/10*16+value%10;
}

void be_stoc(uint8_t *buf, uint16_t val)
{
    buf[0] = val >> 8;
    buf[1] = val >> 0;
}
void le_stoc(uint8_t *buf, uint16_t val)
{
    buf[0] = val >> 0;
    buf[1] = val >> 8;
}


uint32_t be_ctol(const uint8_t *buf)
{
    return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3] << 0);
}

uint32_t le_ctol(const uint8_t *buf)
{
    return (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
}

void be_ltoc(uint8_t *buf, uint32_t val)
{
    buf[0] = val >> 24;
    buf[1] = val >> 16;
    buf[2] = val >> 8;
    buf[3] = val >> 0;
}

void le_ltoc(uint8_t *buf, uint32_t val)
{
    buf[0] = val >> 0;
    buf[1] = val >> 8;
    buf[2] = val >> 16;
    buf[3] = val >> 24;
}
void array_reverse(uint8_t *data,uint32_t length){
    uint8_t tmpvalue=0;
    for(uint32_t i=0;i<length/2;i++){
        tmpvalue=data[i];
        data[i]=data[length-i-1];
        data[length-i-1]=tmpvalue;
    }
}
void printfArray(const uint8_t *data,uint32_t length){
    for(uint32_t i=0;i<length;i++)
        printf("%02X ",data[i]);
    printf("\n");
    fflush(stdout);
}

bool judgeIPAddrIsValidQString(QString ipaddr){

    QStringList ipSectList=ipaddr.split(".");
    if(ipSectList.size() !=4)
        return false;
    int zeroNum=0;
    for (QString ipsect : ipSectList){
        bool ok=false;
        ipsect.toUInt(&ok);
        if(!ok || ipsect.toUInt(&ok)>256)
            return false;
        if(ipsect.toUInt(&ok)==0)
            zeroNum++;
    }

    return (zeroNum!=4);
}


bool judgeHostnameIsValid(const QString hostname){

    QStringList strlist=hostname.split(".");
    if(strlist.size()<1){
        return false;
    }
    for(QString itemstr : strlist){
        itemstr=itemstr.toLower();
        for (int i =0;i<itemstr.size();i++){
            if (itemstr[i].isDigit())
                continue;
            else if (itemstr[i].isLetter())
                continue;
            else
                return false;
        }
    }
    return true;
}

bool checkStr2int(QString str,int &value){
    bool ok=false;
    str.toInt(&ok,10);
    if(ok)
       value=str.toInt(&ok,10);
    return ok;
}

bool checkStr2uint16(QString str,uint16_t &value){
    bool ok=false;
    str.toUShort(&ok,10);
    if(ok)
       value=str.toUShort(&ok,10);
    return ok;
}
bool checkStr2uint32(QString str,uint32_t &value){
    bool ok=false;
    str.toUInt(&ok,10);
    if(ok)
       value=str.toUInt(&ok,10);
    return ok;
}
bool checkStr2uint64(QString str,uint64_t &value){
    bool ok=false;
    str.toULongLong(&ok,10);
    if(ok)
       value=str.toULongLong(&ok,10);
    return ok;
}

bool checkStrHex2uint16(QString str,uint16_t &value){
    bool ok=false;
    str.toUShort(&ok,16);
    if(ok)
       value=str.toUShort(&ok,16);
    return ok;
}

bool checkStrHex2uint32(QString str,uint32_t &value){
    bool ok=false;
    str.toUInt(&ok,16);
    if(ok)
       value=str.toUInt(&ok,16);
    return ok;
}


bool checkStrHex2uint64(QString str,uint64_t &value){
    bool ok=false;
    str.toULongLong(&ok,16);
    if(ok)
       value=str.toULongLong(&ok,16);
    return ok;
}

bool checkStr2float(QString str,float &value){

    bool ok=false;
    str.toFloat(&ok);
    if(ok)
       value=str.toFloat(&ok);
    return ok;
}




bool isValidMacQString(const QString value)
{

  QRegExp reg("^[0-9A-F]\\([0-9A-F]\\:[0-9A-F]\\)\\{5\\}[0-9A-F]$");
  QStringList maclist=value.toUpper().split(':');
  if(maclist.size()!=MAC_ADDR_LEN)
      return false;
  for(int i=0;i<MAC_ADDR_LEN;i++){
      QString itemstr=maclist.at(i);
      std::string str = itemstr.toUpper().toStdString();
      const char* ch = str.c_str();
      if(itemstr.length()!=2)
          return false;
      for(int i=0;i<str.length();i++){
          bool digitValid=ch[i]>='0'&&ch[i]<='9';
          bool letterValid=ch[i]>='A'&&ch[i]<='F';
          if(!(digitValid || letterValid))
              return false;
      }
  }

  return true;
}

bool isValidIpQString(const QString value)
{
  QRegExp reg("^[0-9]\\{1,3\\}\\.[0-9]\\{1,3\\}\\.[0-9]\\{1,3\\}\\.[0-9]\\{1,3\\}$");
  return reg.exactMatch(value);
}
bool checkSensorNoValid(const QString serialno){
    std::string str = serialno.toUpper().toStdString();
    const char* ch = str.c_str();
    for(int i=0;i<str.length();i++){
        bool digitValid=ch[i]>='0'&&ch[i]<='9';
        bool letterValid=ch[i]>='A'&&ch[i]<='F';
        if(!(digitValid || letterValid))
            return false;
    }
    return true;
}




void getIpaddrBytes(const QString ipaddrstr,IPADDR ipaddr){
    QStringList  ipstrList=ipaddrstr.split('.');

    for(int i = 0; i< ipstrList.size();i++){
        bool ok;
        QString tmp = ipstrList.at(i);
        ipaddr[i]=tmp.toInt(&ok,10);
    }
}

static uint8_t str2uint8(QString strvalue){
    std::string str = strvalue.toUpper().toStdString();
    const char* ch = str.c_str();
    uint8_t hightC=0;
    uint8_t lowC=0;
    bool digitValid=ch[0]>='0'&&ch[0]<='9';
    bool letterValid=ch[0]>='A'&&ch[0]<='F';
    if(digitValid)
        hightC=ch[0]-'0'+0;
    else if(letterValid)
        hightC= ch[0]-'A'+10;

    digitValid=ch[1]>='0'&&ch[1]<='9';
    letterValid=ch[1]>='A'&&ch[1]<='F';
    if(digitValid)
        lowC=ch[1]-'0'+0;
    else if(letterValid)
        lowC= ch[1]-'A'+10;

    return (hightC*16+lowC);
}

void getMacaddrBytes(const QString macaddrstr,MACADDR macaddr){
    QStringList  macStrList = macaddrstr.toUpper().split(':');
    for(int i = 0; i< macStrList.size();i++){
        QString valuestr = macStrList.at(i);
        macaddr[i]=str2uint8(valuestr);
    }
}

QString bytes2Str(const uint8_t *data,int len){
    char buff[MAX_BUFF_SIZE]={0};
    for(int i=0;i<len;i++){
        char tmpb[10]={0};
        sprintf(tmpb,"%02X ",data[i]);
        strcat(buff,tmpb);
    }
    return QString(buff);
}

QString float2Str(float *data,int len){
    char buff[MAX_BUFF_SIZE]={0};
    for(int i=0;i<len;i++){
        char tmpb[10]={0};
        if(i!=0)
            sprintf(tmpb,"%.3f,",data[i]);
        else
            sprintf(tmpb,"%.3f",data[i]);
        strcat(buff,tmpb);
    }
    return QString(buff);

}

typedef union
{
    float fdata;
    uint8_t udata[4];
}FloatLongType;

float  Byte_to_Float(uint8_t byte[])
{
    FloatLongType fl;
    fl.udata[0]=byte[0];
    fl.udata[1]=byte[1];
    fl.udata[2]=byte[2];
    fl.udata[3]=byte[3];
    return fl.fdata;
}

float bytes2float(const uint8_t *data){
    float value=-9999;
    uint8_t tmpbyte[4]={0};
    uint8_t byte0=0,byte1=0,byte2=0,byte3=0;
    memcpy(tmpbyte,data,4);
    byte0=tmpbyte[0];
    byte1=tmpbyte[1];
    byte2=tmpbyte[2];
    byte3=tmpbyte[3];

    tmpbyte[0]=byte1;
    tmpbyte[1]=byte0;
    tmpbyte[2]=byte3;
    tmpbyte[3]=byte2;
    memcpy(&value,tmpbyte,4);
    //value=Byte_to_Float(tmpbyte);
    return value;
}

QString bytes2Ipaddr(const uint8_t *data){
    char buff[MAX_BUFF_SIZE]={0};
    for(int i=0;i<IPADDR_LEN;i++){
        char tmpb[10]={0};
        if(i!=IPADDR_LEN-1)
            sprintf(tmpb,"%d.",data[i]);
        else
            sprintf(tmpb,"%d",data[i]);
        strcat(buff,tmpb);
    }
    return QString(buff);
}

QString bytes2MacAddr(const uint8_t *data){
    char buff[MAX_BUFF_SIZE]={0};
    for(int i=0;i<MAC_ADDR_LEN;i++){
        char tmpb[10]={0};
        if(i!=MAC_ADDR_LEN-1)
            sprintf(tmpb,"%02x:",data[i]);
        else
            sprintf(tmpb,"%02x",data[i]);
        strcat(buff,tmpb);
    }
    return QString(buff);
}






uint64_t getTimeStamp(){
         return QDateTime::currentDateTime().toSecsSinceEpoch();
}


bool mapHaveKey(const QMap<uint8_t,int> &rs485AddrMap,uint8_t key){
    QList<uint8_t> keys=rs485AddrMap.keys();
    for(uint8_t keyItem : keys){
        if(keyItem==key)
            return true;
    }
    return false;
}

uint8_t bcd2decimal(uint8_t bcd_num){
    return ((bcd_num / 16) * 10) + (bcd_num % 16);
}


void reverseBytesStep(uint8_t *data,int length){
    if(length%2==1)
        return ;
    for(int ii=0;ii<length;ii++){
        uint8_t tmpValue=data[ii];
        data[ii]=data[ii+1];
        data[ii+1]=tmpValue;
        ii++;
    }
}


